package com.xiaolong.encry.sm;

import cn.hutool.core.lang.Pair;
import cn.hutool.core.util.HexUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.BCUtil;
import cn.hutool.crypto.SmUtil;
import cn.hutool.crypto.asymmetric.KeyType;
import cn.hutool.crypto.asymmetric.SM2;
import org.bouncycastle.crypto.params.ECPrivateKeyParameters;
import org.bouncycastle.crypto.params.ECPublicKeyParameters;
import org.bouncycastle.jcajce.provider.asymmetric.ec.BCECPrivateKey;
import org.bouncycastle.jcajce.provider.asymmetric.ec.BCECPublicKey;
import org.bouncycastle.util.encoders.Base64;

import java.math.BigInteger;
import java.util.HashMap;
import java.util.Map;

public class Sm2Util {

    public static void main(String[] args) {

        System.out.println(generateCompactSM2KeyPair());
//        System.out.println(generator());
//        System.out.println(generatorH5());
//        System.out.println(generatorForFrontend());
        //MIGTAgEAMBMGByqGSM49AgEGCCqBHM9VAYItBHkwdwIBAQQgffMtcBYr5SpThupe/uD9WTDzytsUYEDXHsDXFnfuhHygCgYIKoEcz1UBgi2hRANCAATsDaltco7Jya+X3jVwRUaSsqg/lILphFsvJlqftb+h1KRaS6T7MTAr3neaDUAl3x+Ci77XUYC9YXPvEm9WKAAZ,
        // publicKey=04ec0da96d728ec9c9af97de3570454692b2a83f9482e9845b2f265a9fb5bfa1d4a45a4ba4fb31302bde779a0d4025df1f828bbed75180bd6173ef126f56280019

        System.out.println(Sm2Util.decode("383133973c33","AJQe2swD4GNMfEhnhJX5FBFiW4Lwfn3nW1ax2XseCW4p",null));
    }

    public static String encode(String plaintext, String priKey, String pubKey) {
        SM2 sm2 = SmUtil.sm2(priKey, pubKey);
        byte[] encrypted = sm2.encrypt(StrUtil.utf8Bytes(plaintext), KeyType.PublicKey);
        return cn.hutool.core.codec.Base64.encode(encrypted);
    }

    public static String decode(String ciphertext, String priKey, String pubKey) {
        SM2 sm2 = SmUtil.sm2(priKey, pubKey);
        byte[] decrypted = sm2.decrypt(cn.hutool.core.codec.Base64.decode(ciphertext), KeyType.PrivateKey);
        return StrUtil.utf8Str(decrypted);
    }

    public static String sm3(String password) {
        return SmUtil.sm3(password);
    }

    public static Map<String, String> generateCompactSM2KeyPair() {
        SM2 sm2 = SmUtil.sm2();

        // Get the private key as a BigInteger
        BCECPrivateKey privateKey = (BCECPrivateKey) sm2.getPrivateKey();
        byte[] privateKeyBytes = privateKey.getD().toByteArray();

        // Get the public key point coordinates
        BCECPublicKey publicKey = (BCECPublicKey) sm2.getPublicKey();
        byte[] publicKeyBytes = publicKey.getQ().getEncoded(true);  // Use compressed format

        // Encode both keys to Base64
        String privateKeyBase64 = Base64.toBase64String(privateKeyBytes);
        String publicKeyBase64 = Base64.toBase64String(publicKeyBytes);

        Map<String, String> keyPair = new HashMap<>();
        keyPair.put("privateKey", privateKeyBase64);
        keyPair.put("publicKey", publicKeyBase64);

        return keyPair;
    }


    public static Pair<String, String> generator() {
        // 生成SM2密钥对
        SM2 sm2 = SmUtil.sm2();
        //这里会自动生成对应的随机秘钥对
        byte[] privateKey = BCUtil.encodeECPrivateKey(sm2.getPrivateKey());
        //这里默认公钥压缩  公钥的第一个字节用于表示是否压缩 02或者03表示是压缩公钥,04表示未压缩公钥
        byte[] publicKey = BCUtil.encodeECPublicKey(sm2.getPublicKey());
        //这里得到未压缩的公钥  byte[] publicKey = ((BCECPublicKey) sm2.getPublicKey()).getQ().getEncoded(false);
        String priKey = HexUtil.encodeHexStr(privateKey);
        String pubKey = HexUtil.encodeHexStr(publicKey);
        return Pair.of(priKey, pubKey);
    }

    public static SM2KeyPair generatorH5() {
        SM2 sm2= SmUtil.sm2();
        // 公钥
        String publickey=sm2.getPublicKeyBase64();
        // 前端公钥
        String publicQkey = HexUtil.encodeHexStr(((BCECPublicKey)sm2.getPublicKey()).getQ().getEncoded(false));
        // 私钥
        String privatekey=sm2.getPrivateKeyBase64();
        return new SM2KeyPair(publickey,publicQkey,privatekey);
    }
    public static Map<String, String> generatorForFrontend() {
        // Generate SM2 key pair
        SM2 sm2 = SmUtil.sm2();

        // Get the private key in Base64 format
        String privateKeyBase64 = sm2.getPrivateKeyBase64();

        // Get the uncompressed public key
        byte[] uncompressedPublicKey = ((BCECPublicKey) sm2.getPublicKey()).getQ().getEncoded(false);
        String publicKeyHex = HexUtil.encodeHexStr(uncompressedPublicKey);

        // Create a map to hold both keys
        Map<String, String> keyPair = new HashMap<>();
        keyPair.put("privateKey", privateKeyBase64);
        keyPair.put("publicKey", publicKeyHex);

        return keyPair;
    }



    public static class SM2KeyPair{
        private String publickey;
        private String publicQkey;
        private String privatekey;

        public SM2KeyPair(String publickey, String publicQkey, String privatekey) {
            this.publickey = publickey;
            this.publicQkey = publicQkey;
            this.privatekey = privatekey;
        }

        public String getPublickey() {
            return publickey;
        }

        public void setPublickey(String publickey) {
            this.publickey = publickey;
        }

        public String getPublicQkey() {
            return publicQkey;
        }

        public void setPublicQkey(String publicQkey) {
            this.publicQkey = publicQkey;
        }

        public String getPrivatekey() {
            return privatekey;
        }

        public void setPrivatekey(String privatekey) {
            this.privatekey = privatekey;
        }

        @Override
        public String toString() {
            return "SM2KeyPair{" +
                    "publickey='" + publickey + '\'' +
                    ", publicQkey='" + publicQkey + '\'' +
                    ", privatekey='" + privatekey + '\'' +
                    '}';
        }
    }
}
